package base.list;

import base.util.ByteFileIOUtils;
import base.util.XMLUtils;


import java.io.File;

/**
 * Fat的类，使用枚举实现单例模式
 * Fat对象被创建，提供了一种访问其唯一的对象的方式，即Fat.SIGLETON.getFat()
 * @Author: x1aolone
 * @Date: 2019/9/26 15:17
 */

public enum FatSingleton {

    INSTANCE;

    /**
     * 文件分配表的长度
     */
    private final int FAT_LENGTH = 128;

    /**
     * 从文件中读取Fat时需要跳过的字节数
     */
    private final int SKIP_FILE_BYTES_LENGTH = 0;

    /**
     * 文件分配表，长度为128字节的数组，对应磁盘128块
     * 磁盘每块64字节，文件分配表需占用两块磁盘
     * fat[i]表示第i号块所放文件的下一个块号
     * fat[i]为0时表示该块空闲，不为0时表示已分配，为254表示盘块损坏(-2)，为255(-1)表示文件结束
     * 磁盘的第0块和第1块被FAT占用，fat[0]和fat[1]为255，fat[2]用作根目录，不为0
     */
    private byte[] fat;

    /**
     * 构造方法，从文件中获取对象数据
     * JVM保证这个方法只调用一次，并且是私有的
     */
    FatSingleton() {
        // 使用相对路径来创建文件，java.io默认定位到当前用户目录("user.dir")下，即工程根目录
        // 相对路径的起始处无斜杆"/"
        File file = new File(XMLUtils.getFilePath("disk"));
        fat = ByteFileIOUtils.read(file, FAT_LENGTH, SKIP_FILE_BYTES_LENGTH);
    }


   /**
     * 回收磁块：回收第x块，FAT[index] = 0
     */
    public void gc(int index) {
        if (0 <= index && index < FAT_LENGTH) {
            fat[index] = 0;
        } else {
            throw new ArrayIndexOutOfBoundsException();
        }
    }

    /**
     * 返回数组长度
     * @return 数组长度
     */
    public int size () {
        return FAT_LENGTH;
    }

    /**
     * 返回Fat中下标为index的元素内容
     * @param index 目标元素的下标
     * @return 下标对应的元素内容
     */
    public byte get (int index) {
        if (0 <= index && index < FAT_LENGTH) {
            return fat[index];
        } else {
            return 0;
        }
    }

    /**
     * 设置文件分配表，找到下标为index的目标元素，并把内容更改为content
     * @param index 目标元素的下标
     * @param content 目标元素的新内容
     */
    public void set(int index, byte content) {
        if (0 <= index && index < FAT_LENGTH) {
            fat[index] = content;
        } else {
            throw new ArrayIndexOutOfBoundsException();
        }
    }
    /**
     * 设置文件分配表，找到下标为index的目标元素，并把内容更改为content
     * @param index 目标元素的下标
     * @param content 目标元素的新内容，类型为int
     */
    public void set(int index, int content) {
        if (Byte.MIN_VALUE<= content && content <= Byte.MAX_VALUE) {
            set(index, (byte)content);
        } else {
            throw new RuntimeException("content超出byte的值范围");
        }
    }

    /**
     * 把fat中的内容写入文件
     */
    public void writeIntoFile() {
        // 使用相对路径来创建文件，java.io默认定位到当前用户目录("user.dir")下，即工程根目录
        // 相对路径的起始处无斜杆"/"
        File file = new File(XMLUtils.getFilePath("disk"));
        ByteFileIOUtils.write(file, fat, SKIP_FILE_BYTES_LENGTH);
    }

}
